﻿using System;
namespace Sl.Duplex {

	public abstract class IDuplex: IDisposable{
		private bool disposedValue;
		public Action<string> dLogLine { get; set; }
		public long Read_count { get; protected set; } = 0;
		public long Write_count { get; protected set; } = 0;
		public abstract string Name { get; }
		public abstract bool IsRunning { get; }
		public abstract void openPort();
		public abstract void closePort();

		/// <summary>
		/// 对端口进行配置
		/// </summary>
		/// <param name="str">配置使用的字符串</param>
		/// <returns>如果无问题，则返回Null或者空字符串；
		/// 如果有警告，返回错误原因；
		/// 如果配置失败，返回以【错误】开头的字符串</returns>
		public abstract string config(string str);

		/// <summary>
		/// 收到数据后，如果recvOneByte不为null，
		/// 则将收到的数据交付到RecvOneByte
		/// </summary>
		public Action<IDuplex, byte> RecvOneByte { get; set; } = null;
		/// <summary>
		/// 收到数据后，如果recvOneByte为null，而RecvMutBytes不为null， 
		/// 则将收到的数据交付到RecvMutBytes
		/// </summary>
		public Action<IDuplex, byte[], int, int> RecvMutBytes { get; set; } = null;

		/// <summary>
		/// 收到数据后，如果recvOneByte和RecvMutBytes都为null，
		/// 则执行 dDataToRead，并且将受到的数据缓存，
		/// 后续的数据将通过Read和ReadByte函数异步读取。
		/// </summary>
		public Action<IDuplex> dDataToRead { get; set; } = null;
		public abstract int Read(byte[] buffer, int offset, int count);
		public abstract int ReadByte();
		public abstract void Write(byte[] buffer, int offset, int count);
		public abstract void WriteByte(byte value);
		protected void countRead(int num){
			Read_count += num;
		}
		protected void countWrite(int num) {
			Write_count += num;
		}
		public void clearCount() {
			Write_count = 0;
			Read_count = 0;
		}
		public event Action<IDuplex> ePortStatusChange;
		protected virtual void onPortStatusChange() {
			ePortStatusChange?.Invoke(this);
		}








		protected virtual void Dispose(bool disposing) {
			if (!disposedValue) {
				if (disposing) {
					// TODO: 释放托管状态(托管对象)
				}

				// TODO: 释放未托管的资源(未托管的对象)并重写终结器
				// TODO: 将大型字段设置为 null
				disposedValue = true;
			}
		}

		// // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
		// ~IDuplexPort()
		// {
		//     // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
		//     Dispose(disposing: false);
		// }

		public void Dispose() {
			// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
			Dispose(disposing: true);
			GC.SuppressFinalize(this);
		}
	}
}
